//============================================================================
// Name        : robotica.cpp
// Author      : inzirpask
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <unistd.h>
#include "Dalek.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
using namespace std;

int *createPipe();
void setAllPipes(Dalek *dalekCan,Dalek *dalekSec,Dalek *dalekThay,Dalek *dalekJast);
void createProcesses(Dalek *dalekCan,Dalek *dalekSec,Dalek *dalekThay,Dalek *dalekJast);

int main()
{
	Dalek *dalekCan=NULL;
	dalekCan=new Dalek("dalekCan","localhost:6665",0,0,0,0);
	Dalek *dalekSec=NULL;
	dalekSec=new Dalek("dalekSec","localhost:6665",1,1,1,0);
	Dalek *dalekThay=NULL;
	dalekThay=new Dalek("dalekThay","localhost:6665",2,2,2,0);
	Dalek *dalekJast=NULL;
	dalekJast=new Dalek("dalekJast","localhost:6665",3,3,3,0);
	//Dalek *dalekWho=NULL;
	//dalekWho=new Dalek("dalekWho","localhost:6665",4,4,4,0);

	setAllPipes(dalekCan,dalekSec,dalekThay,dalekJast);
	createProcesses(dalekCan,dalekSec,dalekThay,dalekJast);

	return 0;
}

void createProcesses(Dalek *dalekCan,Dalek *dalekSec,Dalek *dalekThay,Dalek *dalekJast)
{
	/* code by processes */
	pid_t pid0,pid1,pid2;

	pid0=fork();

	if(pid0<0) /* creation error read errno */
	{
		cout << "Error on child 0 creation" << strerror(errno) << endl;
		exit(-1);
	}
	else if(pid0==0) /* child0 */
	{
		cout<<"can run"<<endl;
		dalekCan->run();
	}
	if(pid0!=0) /* parent0 */
	{
		pid1=fork();
		if(pid1<0) /* creation error read errno */
		{
			cout << "Error on child 1 creation" << strerror(errno) << endl;
			exit(-1);
		}else if(pid1==0) /* child1 */
		{
			cout << "sec run"<<endl;
			dalekSec->run();
		}
		if(pid1!=0) /* parent1 */
		{
			pid2=fork();
			if(pid2<0) /* creation error read errno */
			{
				cout << "Error on child 2 creation" << strerror(errno) << endl;
				exit(-1);
			}else if(pid2==0) /* child2 */
			{
				cout<<"jast run"<<endl;
				dalekJast->run();
			}
			if(pid2!=0) /* parent2 */
			{
				cout<<"thay run"<<endl;
				dalekThay->run();
			}
		}
	}
}

void setAllPipes(Dalek *dalekCan,Dalek *dalekSec,Dalek *dalekThay,Dalek *dalekJast)
{
	int *pCanToSec=createPipe();
	int *pSecToCan=createPipe();
	dalekCan->setPipes(pCanToSec[1],pSecToCan[0],dalekSec->getName());
	dalekSec->setPipes(pSecToCan[1],pCanToSec[0],dalekCan->getName());
	int *pCanToThay=createPipe();
	int *pThayToCan=createPipe();
	dalekCan->setPipes(pCanToThay[1],pThayToCan[0],dalekThay->getName());
	dalekThay->setPipes(pThayToCan[1],pCanToThay[0],dalekCan->getName());
	int *pCanToJast=createPipe();
	int *pJastToCan=createPipe();
	dalekCan->setPipes(pCanToJast[1],pJastToCan[0],dalekJast->getName());
	dalekJast->setPipes(pJastToCan[1],pCanToJast[0],dalekCan->getName());
	int *pSecToThay=createPipe();
	int *pThayToSec=createPipe();
	dalekSec->setPipes(pSecToThay[1],pThayToSec[0],dalekThay->getName());
	dalekThay->setPipes(pThayToSec[1],pSecToThay[0],dalekSec->getName());
	int *pSecToJast=createPipe();
	int *pJastToSec=createPipe();
	dalekSec->setPipes(pSecToJast[1],pJastToSec[0],dalekJast->getName());
	dalekJast->setPipes(pJastToSec[1],pSecToJast[0],dalekSec->getName());
	int *pThayToJast=createPipe();
	int *pJastToThay=createPipe();
	dalekThay->setPipes(pThayToJast[1],pJastToThay[0],dalekJast->getName());
	dalekJast->setPipes(pJastToThay[1],pThayToJast[0],dalekThay->getName());

	/*
	int *pCanToSec=createPipe();
	int *pSecToCan=createPipe();
	dalekCan->setPipes(pCanToSec[1],pSecToCan[0]);
	dalekSec->setPipes(pSecToCan[1],pCanToSec[0]);
	int *pCanToThay=createPipe();
	int *pThayToCan=createPipe();
	dalekCan->setPipes(pCanToThay[1],pThayToCan[0]);
	dalekThay->setPipes(pThayToCan[1],pCanToThay[0]);
	int *pCanToJast=createPipe();
	int *pJastToCan=createPipe();
	dalekCan->setPipes(pCanToJast[1],pJastToCan[0]);
	dalekJast->setPipes(pJastToCan[1],pCanToJast[0]);
	int *pSecToThay=createPipe();
	int *pThayToSec=createPipe();
	dalekSec->setPipes(pSecToThay[1],pThayToSec[0]);
	dalekThay->setPipes(pThayToSec[1],pSecToThay[0]);
	int *pSecToJast=createPipe();
	int *pJastToSec=createPipe();
	dalekSec->setPipes(pSecToJast[1],pJastToSec[0]);
	dalekJast->setPipes(pJastToSec[1],pSecToJast[0]);
	int *pThayToJast=createPipe();
	int *pJastToThay=createPipe();
	dalekThay->setPipes(pThayToJast[1],pJastToThay[0]);
	dalekJast->setPipes(pJastToThay[1],pThayToJast[0]);
*/
	//state pipes
	int *pCanToSecState=createPipe();
	int *pSecToCanState=createPipe();
	dalekCan->setStatePipes(pCanToSecState[1],pSecToCanState[0]);
	dalekSec->setStatePipes(pSecToCanState[1],pCanToSecState[0]);
	int *pCanToThayState=createPipe();
	int *pThayToCanState=createPipe();
	dalekCan->setStatePipes(pCanToThayState[1],pThayToCanState[0]);
	dalekThay->setStatePipes(pThayToCanState[1],pCanToThayState[0]);
	int *pCanToJastState=createPipe();
	int *pJastToCanState=createPipe();
	dalekCan->setStatePipes(pCanToJastState[1],pJastToCanState[0]);
	dalekJast->setStatePipes(pJastToCanState[1],pCanToJastState[0]);
	int *pSecToThayState=createPipe();
	int *pThayToSecState=createPipe();
	dalekSec->setStatePipes(pSecToThayState[1],pThayToSecState[0]);
	dalekThay->setStatePipes(pThayToSecState[1],pSecToThayState[0]);
	int *pSecToJastState=createPipe();
	int *pJastToSecState=createPipe();
	dalekSec->setStatePipes(pSecToJastState[1],pJastToSecState[0]);
	dalekJast->setStatePipes(pJastToSecState[1],pSecToJastState[0]);
	int *pThayToJastState=createPipe();
	int *pJastToThayState=createPipe();
	dalekThay->setStatePipes(pThayToJastState[1],pJastToThayState[0]);
	dalekJast->setStatePipes(pJastToThayState[1],pThayToJastState[0]);
}

int *createPipe()
{
	int *piped;
	piped=(int *)malloc(2*(sizeof(int)));
	if(pipe(piped)==-1)
	{
		cout<<"Pipe creation error! errno: "<< errno<<" -- "<<strerror(errno)<<endl;
		exit(-1);
	}

	fcntl(piped[0], F_SETFL, O_NONBLOCK);
	return piped;
}
